<?php
/**
 * Generic class for image manipulation
 * 
 * based on GD
 */   
abstract class Image extends File
{
  
  protected $imageBuffer;
  
  /**
   * Sets the image path and buffer
   * 
   * @param string image path
   * @param boolean initBuffer
   */      
  public function __construct($path,$initBuffer=true)
  {
    parent::__construct($path);
    if($initBuffer=true){$this->initBufferFromFile();}
  }
  
  /**
   * inits the buffer from file
   */     
  public function initBufferFromFile()
  {
    $this->imageBuffer = $this->getImageFromFile($this->path);
  }
  
  /**
   * get buffer X size
   */     
  public function getX()
  {
    return(imagesx($this->imageBuffer));
  }
  
  /**
   * get buffer Y size
   */     
  public function getY()
  {
    return(imagesy($this->imageBuffer));
  }
  
  /**
   * get file X size
   */     
  public function getXfromFile()
  {
    $infos  = getimagesize($this->path);
    return($infos[0]);
  }
  /**
   * get file Y size
   */     
  public function getYfromFile()
  {
    $infos  = getimagesize($this->path);
    return($infos[1]);
  }
  
  /**
   * resize buffered image keeping its scale locked
   * 
   * Unless you specify it, the X is the reference side
   * @param integer new size
   * @param string reference side (x or y)
   */                 
  public function resizeKeepScale($new_value,$side="x")
  {
    if((int)$new_value!=0)
    {
      if($side=="x")
      {
        $factor = ($this->getX())/((int)$new_value);
        $new_y  = round(($this->getY())/$factor);
        $this->resize((int)$new_value,$new_y);
      }
      if($side=="y")
      {
        $factor = ($this->getY())/((int)$new_value);
        $new_x  = round(($this->getX())/$factor);
        $this->resize($new_x,(int)$new_value);
      }
    }
    else
    {
      throw new Exception('Can\'t resize image to 0 pixel !');
    }
  }
  
  /**
   * Resize the buffered image according to a certain square size, keeping it
   * scaled
   * 
   * @param integer size of square (in pixel)
   */   
  public function fitScaleToSquare($size)
  {
    if($this->getX() > $this->getY())
    {
      $this->resizeKeepScale((int)$size);
    }
    else{
      $this->resizeKeepScale((int)$size,"y");
    }
  }
  
  abstract protected function getImageFromFile($path);
  abstract protected function putImageToFile($res,$path);
  
  public function resize($new_x,$new_y)
  {
   if(!empty($this->imageBuffer))
    {
      $to = imagecreatetruecolor($new_x, $new_y);
      $from = $this->imageBuffer;
      imagecopyresampled($to, $from, 0, 0, 0, 0, $new_x, $new_y, $this->getX(), $this->getY());
      $this->imageBuffer=$to;
    }
    else
    {
      throw new Exception('Can\'t resize empty image buffer');
    }
  }
  
  public function imageBufferToFile($new_path="")
  {
    if(!empty($this->imageBuffer))
    {
      if(empty($new_path)){$new_path = $this->path;}
      $this->putImagetoFile($this->imageBuffer,$new_path);
    }
    else
    {
      throw new Exception('Can\'t resize empty image buffer');
    }
  }
  
}

/**
 * Jpeg "plugin" for Image class
 */
class Jpg extends Image
{
  public function __construct($path,$initBuffer=true)
  {
    $this->type = "image/jpeg";
    parent::__construct($path,$initBuffer);
  }

  protected function getImageFromFile($path)
  {
    return(imagecreatefromjpeg($path));
  }
  
  protected function putImagetoFile($res,$path)
  {
    if(!imagejpeg($res,$path))
	 {
		throw new Exception("L'image n'a pu être copiée.");
	 }
  }
}

/**
 * Png "plugin" for Image class
 */
class Png extends Image
{
  public function __construct($path,$initBuffer=true)
  {
    $this->type = "image/png";
    parent::__construct($path,$initBuffer);
  }
  
  protected function getImageFromFile($path)
  {
    return(imagecreatefrompng($path));
  }
  
  protected function putImagetoFile($res,$path)
  {
    if(!imagepng($res,$path))
	 {
		throw new Exception("L'image n'a pu être copiée.");
	 }
  }
}

/**
 * Gif "plugin" for Image class
 */ 
class Gif extends Image
{
  public function __construct($path,$initBuffer=true)
  {
    $this->type = "image/gif";
    parent::__construct($path,$initBuffer);
  }

  protected function getImageFromFile($path)
  {
    return(imagecreatefromgif($path));
  }
  
  protected function putImagetoFile($res,$path)
  {
    if(!imagegif($res,$path))
	 {
		throw new Exception("L'image n'a pu être copiée.");
	 }
  }
}

?>
